Skip to content

fix(native): run shutdown in thread in uwsgi#19086

Open
VianneyRuhlmann wants to merge 4 commits into
repro/uwsgi-tokio-panicfrom
vianney/init-tokio-thread-storage-early
Open

fix(native): run shutdown in thread in uwsgi#19086
VianneyRuhlmann wants to merge 4 commits into
repro/uwsgi-tokio-panicfrom
vianney/init-tokio-thread-storage-early

Conversation

@VianneyRuhlmann

@VianneyRuhlmann VianneyRuhlmann commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Description

Fix uwsgi crash caused by the thread local storage being destroyed when calling shutdown.
This is done by running the shared runtime shutdown in a new thread with a clean thread local storage.

This also remove the Drop implementation in the TraceExporter which called shutdown. This was used as a safeguard against dropping a trace exporter without shutting down the workers. This is replace by calling shutdown when the exporter is dropped in the writer to avoid calling it at exit.

Testing

The regression test for uwsgi crash is passing.

Risks

Additional Notes

@cit-pr-commenter-54b7da

cit-pr-commenter-54b7da Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codeowners resolved as

ddtrace/internal/native_runtime.py                                      @DataDog/apm-core-python
ddtrace/internal/writer/writer.py                                       @DataDog/apm-core-python

@datadog-prod-us1-6

datadog-prod-us1-6 Bot commented Jul 15, 2026

Copy link
Copy Markdown

Pipelines  Tests

Unblock PR with BitsAI

⚠️ Warnings

🚦 11 Pipeline jobs failed

DataDog/apm-reliability/dd-trace-py | build linux serverless: [amd64, cp315-cp315, v113741238-d2b8243-manylinux2014_x86_64, 1]   View in Datadog   GitLab

DataDog/apm-reliability/dd-trace-py | build linux serverless: [arm64, cp315-cp315, v113741357-d2b8243-manylinux2014_aarch64, 1]   View in Datadog   GitLab

DataDog/apm-reliability/dd-trace-py | build linux: [amd64, cp315-cp315, v113741491-d2b8243-musllinux_1_2_x86_64]   View in Datadog   GitLab

View all 11 failed jobs.

ℹ️ Info

No other issues found (see more)

🧪 All tests passed
❄️ No new flaky tests detected

🔄 Datadog auto-retried 2 jobs - 2 passed on retry View in Datadog

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 8025fa7 | Docs | Datadog PR Page | Give us feedback!

@VianneyRuhlmann
VianneyRuhlmann changed the base branch from main to repro/uwsgi-tokio-panic July 15, 2026 18:51
@VianneyRuhlmann
VianneyRuhlmann force-pushed the vianney/init-tokio-thread-storage-early branch from 432cbd8 to da2b375 Compare July 15, 2026 19:00
@pr-commenter

pr-commenter Bot commented Jul 15, 2026

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-07-17 17:37:02

Comparing candidate commit 8025fa7 in PR branch vianney/init-tokio-thread-storage-early with baseline commit 3776154 in branch repro/uwsgi-tokio-panic.

Found 0 performance improvements and 8 performance regressions! Performance is the same for 607 metrics, 10 unstable metrics.

scenario:iast_aspects-re_search_aspect

  • 🟥 execution_time [+28.127µs; +33.596µs] or [+9.810%; +11.718%]

scenario:iastaspects-add_aspect

  • 🟥 execution_time [+10.168µs; +12.779µs] or [+9.939%; +12.491%]

scenario:iastaspects-casefold_noaspect

  • 🟥 execution_time [+26.580µs; +37.955µs] or [+8.342%; +11.912%]

scenario:iastaspects-strip_aspect

  • 🟥 execution_time [+71.507µs; +76.470µs] or [+22.625%; +24.195%]

scenario:iastaspectsospath-ospathbasename_aspect

  • 🟥 execution_time [+90.381µs; +101.629µs] or [+21.219%; +23.860%]

scenario:iastaspectssplit-rsplit_aspect

  • 🟥 execution_time [+18.704µs; +26.092µs] or [+12.357%; +17.238%]

scenario:span-start

  • 🟥 execution_time [+1.593ms; +1.751ms] or [+10.379%; +11.413%]

scenario:telemetryaddmetric-1-count-metric-1-times

  • 🟥 execution_time [+225.458ns; +258.394ns] or [+10.715%; +12.280%]

@VianneyRuhlmann
VianneyRuhlmann force-pushed the vianney/init-tokio-thread-storage-early branch from 321c8c0 to f017a82 Compare July 17, 2026 12:35
@VianneyRuhlmann
VianneyRuhlmann marked this pull request as ready for review July 17, 2026 15:31
@VianneyRuhlmann
VianneyRuhlmann requested review from a team as code owners July 17, 2026 15:31
@VianneyRuhlmann
VianneyRuhlmann requested review from avara1986, florentinl and juanjux and removed request for a team July 17, 2026 15:31

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 12f5d61945

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread ddtrace/internal/native_runtime.py Outdated
already been stopped (e.g. via TraceExporter.shutdown).
"""
super().shutdown(timeout_ms=timeout_ms)
using_uwsgi = importlib.util.find_spec("uwsgi") is not None

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use import-based uWSGI detection

When running under uWSGI on Python versions where the server injects the synthetic uwsgi module without a module spec, importlib.util.find_spec("uwsgi") raises ValueError instead of returning a truthy value. Since _atexit() catches that exception, SIGTERM exits skip shutdown_in_thread() entirely, so the uWSGI crash path this change is meant to fix still uses no native-runtime shutdown; use import uwsgi/sys.modules or the existing uWSGI helper and handle ValueError here.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻 I agree with this feedback, I thik uwsgi directly injects the module in sys.modules, so doing a pyimport of uwsgi or checking sys.modules["uwsgi"] would be better

self._test_session_token = token
old_exporter = self._exporter
self._exporter = self._create_exporter()
old_exporter.shutdown(3_000_000_000)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop exporters when recreating stopped writers

This new explicit shutdown covers token/API swaps, but NativeWriter.recreate() still catches ServiceStatusError and returns a new writer without stopping the old exporter when the writer was never started, which happens in fork-child recreation and LLMObs/AppSec reconfiguration before the first trace. Since this commit removed the Rust Drop shutdown fallback, those old exporters leave their SharedRuntime workers registered/running until process exit, causing duplicate native workers after each such recreate; add the same exporter shutdown/drop cleanup on the stopped-writer recreate path.

Useful? React with 👍 / 👎.

@brettlangdon brettlangdon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems ok, do we have a regression test we can add?

Comment thread ddtrace/internal/native_runtime.py Outdated
already been stopped (e.g. via TraceExporter.shutdown).
"""
super().shutdown(timeout_ms=timeout_ms)
using_uwsgi = importlib.util.find_spec("uwsgi") is not None

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻 I agree with this feedback, I thik uwsgi directly injects the module in sys.modules, so doing a pyimport of uwsgi or checking sys.modules["uwsgi"] would be better

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants